//
//  Object.h
//  Simulation
//
//  Created by Christopher Kemsley on 2/27/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#ifndef Simulation_Object_h
#define Simulation_Object_h

#include "Exception.hpp"
#include <vector>
#include <set>


NamespaceBegin



class	ObjectContext ;
class	ObjectContext ;







class	Object
{
protected:
	Object () ;
	
protected:
	friend class ObjectContext ;
	virtual ~Object () ;
	
private:
	ObjectContext&	myContext ;
	
	// Defined but not declared to forcefully disable
	Object ( Object const & c ) ;
	Object& operator= (Object const& c ) ;
} ;





/*
 An ObjectContext must be created an opened before allocating and Object
 subclasses. The context owns every object created whiel it's open (unless
 another context is opened inside). Upon deallocation, it deletes every
 object contained within.
 */

class	ObjectContext
{
public:
	ObjectContext () ;
	~ObjectContext () ;
	
	static ObjectContext&	currentContext () ;
	
	void	open () ;
	void	close () ;
	
	bool	containsObject	( Object * object ) ;
	
	
protected:
	friend class Object ;
	
	void	addObject		( Object * object ) ;
	void	removeObject	( Object * object ) ;
	
	
private:
	typedef std::vector<ObjectContext*>	Contexts ;
	static Contexts&	contextStack () ;
	
	typedef std::set<Object*>	Objects ;
	Objects	mObjects ;
	bool	mIsOpen ;
} ;











/*
 Deleting-Pointer. Owns C++ objects contained within and deletes
 then upon deallocation.
 
 The "<<" is used instead of "=" because it takes ownership instead
 of simply setting it.
 */

template <typename Type>
struct	DP
{
	
	DP	()					: mValue(0) { }
	DP	( Type * inP )		: mValue(inP) { }
	~DP	()					{ if(mValue!=0)delete mValue; }
	
	
	Type*	operator->	() const
		{
		return mValue ;
		}
	Type&	operator*	() const
		{
		return *mValue ;
		}
	
	
	Type*	pointer		() const
		{
		return mValue ;
		}
	
	/* Setting */
	DP<Type>&	operator<<	( Type * inP ) // takes ownership
		{
		delete mValue ;
		mValue = inP ;
		return *this ;
		}
	DP<Type>&	operator<<	( DP<Type> & inP )	// steals the object
		{
		delete mValue ;
		mValue = inP.mValue ;
		inP.mValue = 0 ;
		return *this ;
		}
	
	/* Comparing */
	bool		operator==	( Type * inP ) const
		{
		return mValue == inP ;
		}
	bool		operator==	( DP<Type> const & inP ) const
		{
		return mValue == inP.mValue ;
		}
	bool		operator!=	( Type * inP ) const
		{
		return mValue != inP ;
		}
	bool		operator!=	( DP<Type> const & inP ) const
		{
		return mValue != inP.mValue ;
		}
	
	/* std::vector and set require these */
	bool		operator<	( Type * inP ) const
		{
		return mValue < inP ;
		}
	bool		operator<	( DP<Type> const & inP ) const
		{
		return mValue < inP.mValue ;
		}
	bool		operator>	( Type * inP ) const
		{
		return mValue > inP ;
		}
	bool		operator>	( DP<Type> const & inP ) const
		{
		return mValue > inP.mValue ;
		}
	
private:
	Type	*	mValue ;
	
	// Declared but not implemented
	DP<Type>&	operator=	( Type * inP ) ;
	DP<Type>&	operator=	( DP<Type> const & inP ) ;
} ;




NamespaceEnd

#endif
